"""
用户设置API端点模块

提供用户设置相关的RESTful API接口，包括：
1. 获取用户设置
2. 创建用户设置
3. 更新用户设置
4. 删除用户设置
5. 标题生成功能

主要功能：
- 用户个性化设置管理
- 默认模型配置
- 标题生成模型设置
- 设置验证和错误处理

作者: LLM Chat System
版本: 1.0.0
"""

from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from app.core.logging_config import get_logger

# 导入数据库依赖
from app.database import get_db
# 导入用户设置服务
from app.services.user_settings_service import UserSettingsService
# 导入聊天服务（用于标题生成）
from app.services.chat_service import ChatService
# 导入数据模式
from app.schemas.user_settings import (
    UserSettingsCreate, 
    UserSettingsUpdate, 
    UserSettingsResponse,
    UserSettingsWithModels,
    TitleGenerationRequest,
    TitleGenerationResponse
)
# 导入认证依赖
from app.api.v1.endpoints.auth import get_current_user
from app.models.user import User

# 创建API路由器
router = APIRouter()
# 创建服务实例
user_settings_service = UserSettingsService()
chat_service = ChatService()
# 创建日志记录器
logger = get_logger(__name__)


@router.get("", response_model=UserSettingsWithModels)
async def get_user_settings(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    获取当前用户设置
    
    返回用户的个性化设置，包括默认模型、标题生成模型等配置。
    如果用户设置不存在，将返回默认设置。
    
    Args:
        db: 数据库会话，通过依赖注入获取
        current_user: 当前登录用户，通过JWT token验证
        
    Returns:
        UserSettingsWithModels: 包含模型信息的用户设置
        
    Raises:
        HTTPException: 当获取设置失败时抛出
    """
    try:
        user_id = current_user.id
        logger.info(f"获取用户设置请求: user_id={user_id}")
        
        settings = user_settings_service.get_user_settings_with_models(db, user_id)
        if not settings:
            # 如果设置不存在，创建默认设置
            settings = user_settings_service.get_or_create_user_settings(db, user_id)
            settings = user_settings_service.get_user_settings_with_models(db, user_id)
        
        logger.info(f"获取用户设置成功: user_id={user_id}")
        return settings
        
    except Exception as e:
        logger.error(f"获取用户设置失败: user_id={current_user.id}, error={str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取用户设置失败: {str(e)}"
        )


@router.post("", response_model=UserSettingsResponse)
async def create_user_settings(
    settings_data: UserSettingsCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    创建用户设置
    
    为用户创建个性化设置记录。如果用户已有设置，将返回错误。
    
    Args:
        settings_data: 用户设置数据
        db: 数据库会话，通过依赖注入获取
        current_user: 当前登录用户，通过JWT token验证
        
    Returns:
        UserSettingsResponse: 创建的用户设置
        
    Raises:
        HTTPException: 当创建失败或用户设置已存在时抛出
    """
    try:
        user_id = current_user.id
        logger.info(f"创建用户设置请求: user_id={user_id}")
        
        settings = user_settings_service.create_user_settings(
            db, user_id, settings_data
        )
        
        logger.info(f"创建用户设置成功: user_id={user_id}, settings_id={settings.id}")
        return settings
        
    except ValueError as e:
        logger.error(f"创建用户设置参数错误: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"创建用户设置失败: user_id={current_user.id}, error={str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"创建用户设置失败: {str(e)}"
        )


@router.put("", response_model=UserSettingsResponse)
async def update_user_settings(
    settings_data: UserSettingsUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    更新用户设置
    
    更新用户的个性化设置。如果用户设置不存在，将创建默认设置。
    
    Args:
        settings_data: 更新的设置数据
        db: 数据库会话，通过依赖注入获取
        current_user: 当前登录用户，通过JWT token验证
        
    Returns:
        UserSettingsResponse: 更新后的用户设置
        
    Raises:
        HTTPException: 当更新失败时抛出
    """
    try:
        user_id = current_user.id
        logger.info(f"更新用户设置请求: user_id={user_id}")
        
        settings = user_settings_service.update_user_settings(
            db, user_id, settings_data
        )
        
        logger.info(f"更新用户设置成功: user_id={user_id}")
        return settings
        
    except ValueError as e:
        logger.error(f"更新用户设置参数错误: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"更新用户设置失败: user_id={current_user.id}, error={str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"更新用户设置失败: {str(e)}"
        )


@router.delete("")
async def delete_user_settings(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    删除用户设置
    
    删除用户的个性化设置记录。
    
    Args:
        db: 数据库会话，通过依赖注入获取
        current_user: 当前登录用户，通过JWT token验证
        
    Returns:
        dict: 删除结果消息
        
    Raises:
        HTTPException: 当删除失败时抛出
    """
    try:
        user_id = current_user.id
        logger.info(f"删除用户设置请求: user_id={user_id}")
        
        success = user_settings_service.delete_user_settings(db, user_id)
        
        if success:
            logger.info(f"删除用户设置成功: user_id={user_id}")
            return {"message": "用户设置删除成功"}
        else:
            logger.warning(f"用户设置不存在: user_id={user_id}")
            return {"message": "用户设置不存在"}
        
    except Exception as e:
        logger.error(f"删除用户设置失败: user_id={current_user.id}, error={str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"删除用户设置失败: {str(e)}"
        )


@router.post("/generate-title", response_model=TitleGenerationResponse)
async def generate_conversation_title(
    request: TitleGenerationRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    生成对话标题
    
    使用指定的模型为对话生成标题。
    
    Args:
        request: 标题生成请求
        db: 数据库会话，通过依赖注入获取
        current_user: 当前登录用户，通过JWT token验证
        
    Returns:
        TitleGenerationResponse: 标题生成结果
        
    Raises:
        HTTPException: 当标题生成失败时抛出
    """
    try:
        logger.info(f"生成对话标题请求: conversation_id={request.conversation_id}, user_id={current_user.id}")
        
        # 使用当前登录用户的ID获取用户设置
        user_id = current_user.id
        settings = user_settings_service.get_or_create_user_settings(db, user_id)
        
        # 确定使用的模型ID
        model_id = request.model_id or settings.title_generation_model_id
        if not model_id:
            raise ValueError("未设置标题生成模型")
        
        # 调用聊天服务生成标题（不传递messages，让服务自己从数据库获取完整历史）
        title = await chat_service.generate_conversation_title(
            db=db,
            conversation_id=request.conversation_id,
            messages=None,  # 改为None，让后端从数据库获取
            model_id=model_id,
            user_id=user_id  # 传递用户ID进行权限验证
        )
        
        if title:
            logger.info(f"生成对话标题成功: conversation_id={request.conversation_id}, title='{title}'")
            return TitleGenerationResponse(
                success=True,
                title=title,
                message="标题生成成功",
                model_used=f"Model ID: {model_id}"
            )
        else:
            logger.warning(f"标题生成失败: conversation_id={request.conversation_id}")
            return TitleGenerationResponse(
                success=False,
                title=None,
                message="标题生成失败",
                model_used=None
            )
        
    except ValueError as e:
        logger.error(f"生成标题参数错误: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"生成对话标题失败: conversation_id={request.conversation_id}, error={str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"生成对话标题失败: {str(e)}"
        )


@router.get("/data-directories")
async def get_data_directories():
    """
    获取数据目录信息
    
    Returns:
        dict: 数据目录信息
    """
    try:
        import os
        from pathlib import Path
        
        # 获取当前工作目录
        current_dir = os.getcwd()
        
        # 构建各种数据目录路径
        data_directories = {
            "app_data": current_dir,
            "logs": os.path.join(current_dir, "logs"),
            "uploads": os.path.join(current_dir, "uploads"),
            "chroma_db": os.path.join(current_dir, "chroma_db"),
            "database": os.path.join(current_dir, "llm_chat.db")
        }
        
        # 检查目录是否存在并获取大小
        directory_info = {}
        for name, path in data_directories.items():
            if os.path.exists(path):
                if os.path.isdir(path):
                    # 计算目录大小
                    total_size = 0
                    for dirpath, dirnames, filenames in os.walk(path):
                        for filename in filenames:
                            filepath = os.path.join(dirpath, filename)
                            try:
                                total_size += os.path.getsize(filepath)
                            except (OSError, IOError):
                                pass
                    directory_info[name] = {
                        "path": path,
                        "exists": True,
                        "size": total_size,
                        "size_mb": round(total_size / (1024 * 1024), 2)
                    }
                else:
                    # 文件
                    try:
                        size = os.path.getsize(path)
                        directory_info[name] = {
                            "path": path,
                            "exists": True,
                            "size": size,
                            "size_mb": round(size / (1024 * 1024), 2)
                        }
                    except (OSError, IOError):
                        directory_info[name] = {
                            "path": path,
                            "exists": False,
                            "size": 0,
                            "size_mb": 0
                        }
            else:
                directory_info[name] = {
                    "path": path,
                    "exists": False,
                    "size": 0,
                    "size_mb": 0
                }
        
        return directory_info
        
    except Exception as e:
        logger.error(f"获取数据目录信息失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取数据目录信息失败: {str(e)}"
        )


@router.post("/clear-cache")
async def clear_cache():
    """
    清除缓存
    
    Returns:
        dict: 清除结果
    """
    try:
        import os
        import shutil
        from pathlib import Path
        
        current_dir = os.getcwd()
        cache_dirs = [
            os.path.join(current_dir, "chroma_db"),
            os.path.join(current_dir, "logs"),
            os.path.join(current_dir, "__pycache__"),
            os.path.join(current_dir, "app", "__pycache__"),
            os.path.join(current_dir, "app", "api", "__pycache__"),
            os.path.join(current_dir, "app", "api", "v1", "__pycache__"),
            os.path.join(current_dir, "app", "api", "v1", "endpoints", "__pycache__"),
            os.path.join(current_dir, "app", "core", "__pycache__"),
            os.path.join(current_dir, "app", "models", "__pycache__"),
            os.path.join(current_dir, "app", "schemas", "__pycache__"),
            os.path.join(current_dir, "app", "services", "__pycache__")
        ]
        
        cleared_items = []
        total_freed = 0
        
        for cache_dir in cache_dirs:
            if os.path.exists(cache_dir):
                try:
                    if os.path.isdir(cache_dir):
                        # 计算目录大小
                        dir_size = 0
                        for dirpath, dirnames, filenames in os.walk(cache_dir):
                            for filename in filenames:
                                filepath = os.path.join(dirpath, filename)
                                try:
                                    dir_size += os.path.getsize(filepath)
                                except (OSError, IOError):
                                    pass
                        
                        # 删除目录
                        shutil.rmtree(cache_dir)
                        cleared_items.append(f"{cache_dir} ({round(dir_size / (1024 * 1024), 2)} MB)")
                        total_freed += dir_size
                    else:
                        # 删除文件
                        file_size = os.path.getsize(cache_dir)
                        os.remove(cache_dir)
                        cleared_items.append(f"{cache_dir} ({round(file_size / (1024 * 1024), 2)} MB)")
                        total_freed += file_size
                except Exception as e:
                    logger.warning(f"清除缓存项失败: {cache_dir}, error={str(e)}")
        
        return {
            "success": True,
            "message": f"缓存清除完成，共释放 {round(total_freed / (1024 * 1024), 2)} MB",
            "cleared_items": cleared_items,
            "total_freed_mb": round(total_freed / (1024 * 1024), 2)
        }
        
    except Exception as e:
        logger.error(f"清除缓存失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"清除缓存失败: {str(e)}"
        )


@router.post("/delete-knowledge-files")
async def delete_knowledge_files():
    """
    删除知识库文件
    
    Returns:
        dict: 删除结果
    """
    try:
        import os
        from pathlib import Path
        
        current_dir = os.getcwd()
        uploads_dir = os.path.join(current_dir, "uploads")
        chroma_db_dir = os.path.join(current_dir, "chroma_db")
        
        deleted_items = []
        total_freed = 0
        
        # 删除uploads目录中的文件
        if os.path.exists(uploads_dir):
            for filename in os.listdir(uploads_dir):
                file_path = os.path.join(uploads_dir, filename)
                if os.path.isfile(file_path):
                    try:
                        file_size = os.path.getsize(file_path)
                        os.remove(file_path)
                        deleted_items.append(f"uploads/{filename} ({round(file_size / (1024 * 1024), 2)} MB)")
                        total_freed += file_size
                    except Exception as e:
                        logger.warning(f"删除文件失败: {file_path}, error={str(e)}")
        
        # 删除chroma_db目录
        if os.path.exists(chroma_db_dir):
            try:
                # 计算目录大小
                dir_size = 0
                for dirpath, dirnames, filenames in os.walk(chroma_db_dir):
                    for filename in filenames:
                        filepath = os.path.join(dirpath, filename)
                        try:
                            dir_size += os.path.getsize(filepath)
                        except (OSError, IOError):
                            pass
                
                import shutil
                shutil.rmtree(chroma_db_dir)
                deleted_items.append(f"chroma_db/ ({round(dir_size / (1024 * 1024), 2)} MB)")
                total_freed += dir_size
            except Exception as e:
                logger.warning(f"删除chroma_db目录失败: {str(e)}")
        
        return {
            "success": True,
            "message": f"知识库文件删除完成，共释放 {round(total_freed / (1024 * 1024), 2)} MB",
            "deleted_items": deleted_items,
            "total_freed_mb": round(total_freed / (1024 * 1024), 2)
        }
        
    except Exception as e:
        logger.error(f"删除知识库文件失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"删除知识库文件失败: {str(e)}"
        )


@router.get("/system-info")
async def get_system_info():
    """
    获取系统信息
    
    Returns:
        dict: 系统信息
    """
    try:
        import os
        import time
        from datetime import datetime
        
        # 获取应用版本信息
        version = "1.0.0"
        build_time = "2024-01-01 00:00:00"
        
        # 获取系统运行时间（简化版本，不依赖psutil）
        try:
            # 使用应用启动时间作为参考
            uptime_seconds = time.time() - os.path.getctime(__file__)
            days = int(uptime_seconds // 86400)
            hours = int((uptime_seconds % 86400) // 3600)
            minutes = int((uptime_seconds % 3600) // 60)
            uptime = f"{days}天{hours}小时{minutes}分钟"
        except Exception:
            uptime = "未知"
        
        # 获取内存使用情况（简化版本）
        try:
            # 尝试使用psutil，如果失败则使用默认值
            try:
                import psutil
                memory = psutil.virtual_memory()
                memory_usage = f"{memory.used // (1024 * 1024)} MB / {memory.total // (1024 * 1024)} MB ({memory.percent:.1f}%)"
            except ImportError:
                memory_usage = "512 MB / 8192 MB (6.3%)"
        except Exception:
            memory_usage = "未知"
        
        # 获取磁盘使用情况（简化版本）
        try:
            # 尝试使用psutil，如果失败则使用默认值
            try:
                import psutil
                disk = psutil.disk_usage('/')
                disk_usage = f"{disk.used // (1024 * 1024)} MB / {disk.total // (1024 * 1024)} MB ({disk.percent:.1f}%)"
            except ImportError:
                disk_usage = "1024 MB / 100000 MB (1.0%)"
        except Exception:
            disk_usage = "未知"
        
        # 获取网络状态
        try:
            # 简单的网络连接测试
            import socket
            socket.create_connection(("8.8.8.8", 53), timeout=3)
            network_status = "online"
        except Exception:
            network_status = "offline"
        
        return {
            "version": version,
            "build_time": build_time,
            "uptime": uptime,
            "memory_usage": memory_usage,
            "disk_usage": disk_usage,
            "network_status": network_status,
            "timestamp": datetime.now().isoformat()
        }
        
    except Exception as e:
        logger.error(f"获取系统信息失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取系统信息失败: {str(e)}"
        )


@router.post("/reset-all-data")
async def reset_all_data(db: Session = Depends(get_db)):
    """
    重置所有数据
    
    Returns:
        dict: 重置结果
    """
    try:
        from app.models.conversation import Conversation, Message
        from app.models.knowledge_base import KnowledgeBase, Document
        from app.models.user_settings import UserSettings
        from app.models.prompt_template import PromptTemplate
        from app.models.model_config import ModelConfig
        from app.models.user import User
        
        # 删除所有数据
        deleted_counts = {}
        
        # 删除对话和消息
        conversations = db.query(Conversation).all()
        for conv in conversations:
            db.query(Message).filter(Message.conversation_id == conv.id).delete()
        db.query(Conversation).delete()
        deleted_counts["conversations"] = len(conversations)
        
        # 删除知识库和文档
        knowledge_bases = db.query(KnowledgeBase).all()
        for kb in knowledge_bases:
            db.query(Document).filter(Document.knowledge_base_id == kb.id).delete()
        db.query(KnowledgeBase).delete()
        deleted_counts["knowledge_bases"] = len(knowledge_bases)
        
        # 删除用户设置
        user_settings = db.query(UserSettings).all()
        db.query(UserSettings).delete()
        deleted_counts["user_settings"] = len(user_settings)
        
        # 删除提示词模板
        prompts = db.query(PromptTemplate).all()
        db.query(PromptTemplate).delete()
        deleted_counts["prompt_templates"] = len(prompts)
        
        # 删除模型配置（保留默认模型）
        models = db.query(ModelConfig).filter(ModelConfig.is_default == False).all()
        db.query(ModelConfig).filter(ModelConfig.is_default == False).delete()
        deleted_counts["model_configs"] = len(models)
        
        # 删除用户（保留默认用户）
        users = db.query(User).filter(User.id != 1).all()
        db.query(User).filter(User.id != 1).delete()
        deleted_counts["users"] = len(users)
        
        db.commit()
        
        # 删除物理文件
        import os
        import shutil
        
        current_dir = os.getcwd()
        file_dirs = [
            os.path.join(current_dir, "uploads"),
            os.path.join(current_dir, "chroma_db"),
            os.path.join(current_dir, "logs")
        ]
        
        for file_dir in file_dirs:
            if os.path.exists(file_dir):
                try:
                    shutil.rmtree(file_dir)
                except Exception as e:
                    logger.warning(f"删除目录失败: {file_dir}, error={str(e)}")
        
        return {
            "success": True,
            "message": "所有数据重置完成",
            "deleted_counts": deleted_counts
        }
        
    except Exception as e:
        db.rollback()
        logger.error(f"重置所有数据失败: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"重置所有数据失败: {str(e)}"
        )